#pragma once
#include <vector>
#include <queue>
#include <string>
#include <iostream>
#include <unistd.h>
#include <pthread.h>

// 维护线程数量
const int defaultnums = 5;

struct ThreadInfo
{
    pthread_t tid;
    std::string name;
};

template <class T>
class ThreadPool
{
private:
    void Lock()
    {
        pthread_mutex_lock(&mutex_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }
    void Wakeup()
    {
        pthread_cond_signal(&cond_); // 唤醒单个
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&cond_, &mutex_);
    }
    bool IsQueueEmpty()
    {
        return tasks_.empty();
    }

    std::string GetName(const pthread_t &tid)
    {
        for (int i = 0; i < threads_.size(); i++)
        {
            if (threads_[i].tid == tid)
            {
                return threads_[i].name;
            }
        }

        return "None";
    }

public:
    ThreadPool(int num = defaultnums)
        : threads_(num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }

    // 线程的执行函数
    static void *RoutineThread(void *args) // 必须使用静态函数，因为成员函数第一个参数为this指针
    {
        ThreadPool *tp = static_cast<ThreadPool *>(args);
        while (true)
        {
            // 判断队列也是 访问临界资源 访问临界资源就要加锁
            tp->Lock();

            // 如果任务队列为空
            while (tp->IsQueueEmpty()) // 必须使用while 防止伪唤醒
            {
                // 阻塞
                tp->ThreadSleep();
            }

            T tmp = tp->pop(); // 执行任务

            tp->Unlock();

            // std::cout << "name: " << tp->GetName(pthread_self()) << "  result: " << tmp << std::endl;
            tmp.result();
           
            // usleep(1000);
        }

        return nullptr;
    }

    void strat()
    {
        for (int i = 0; i < threads_.size(); i++)
        {
            threads_[i].name = "Thread-" + std::to_string(i + 1);
            pthread_create(&(threads_[i].tid), nullptr, RoutineThread, this);
        }
    }

    void push(const T &out)
    {
        Lock();
        tasks_.push(out);
        Wakeup();

        Unlock();
    }

    T pop()
    {
        // Lock();   //这里不能加锁 应为pop执行的时候是在RoutineThread中,这是已经申请到锁了，再次申请锁会发生死锁

        T tmp = tasks_.front();
        tasks_.pop();

        // Unlock();
        return tmp;
    }

    static ThreadPool<T> *GetInstance()
    {
        if (nullptr == tp_)
        {
            pthread_mutex_lock(&lock_);
            if (tp_ == nullptr)
            {
                tp_ = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }

        return tp_;
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

private:
    std::vector<ThreadInfo> threads_; // 组织线程
    std::queue<T> tasks_;             // 任务队列，临界资源

    pthread_mutex_t mutex_; // 互斥锁，对任务队列互斥属性
    pthread_cond_t cond_;   // 条件变量，对线程同步属性

    // 单例
    static ThreadPool<T> *tp_;
    static pthread_mutex_t lock_;
};

// 类内声明 类外初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;